#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#define MAXSIZE 128
#define MAXARGS 32
// 命令行参数表
char *gargv[MAXARGS];
int gargc = 0;
const char *gseq = " ";

const char* GetUserName()
{
    char* name = getenv("USER");
    if (name == NULL)
        return "None";
    return name;
}

const char* GetHostName()
{
    char* hostname = getenv("HOSTNAME");
    if (hostname == NULL)
        return "None";
    return hostname;
}

const char* GetPwd()
{
    char* pwd = getenv("PWD");
    if (pwd == NULL)
        return "None";
    return pwd;

}

void PrintCommandLine()
{
    // 用户名 主机名 当前路径
    printf("[%s@%s %s]# ", GetUserName(), GetHostName(), GetPwd());
    fflush(stdout);
}

int GetCommandLine(char *commandline, int size)
{
    fgets(commandline, size, stdin);
    commandline[strlen(commandline) - 1] = '\0';

    return strlen(commandline);
}

int ParseCommand(char *commandline)
{
    gargc = 0;
    memset(gargv, 0, sizeof(gargv));

    gargv[0] = strtok(commandline, gseq);
    while (gargv[++gargc] = strtok(NULL, gseq));

    printf("gargc: %d\n", gargc);
    int i = 0;
    for (; gargv[i]; i++)
    {
        printf("gargv[%d]: %s\n", i, gargv[i]);
    }

    return gargc;
}

// return val
// 0 : 不是内建命令
// 1 : 是内建命令 && 执行命令
int CheckBuiltInExecute()
{
    if (strcmp(gargv[0], "cd") == 0)
    {
        if (gargc == 2)
        {
            // 1.修改内核路径
            chdir(gargv[1]);
            // 2.修改环境变量

        }
        return 1;
    }

    return 0;
}

int ExecuteCommand()
{
    pid_t id = fork();
    if (id < 0)
        return -1;
    else if (id == 0)
    {
        // child
        execvp(gargv[0], gargv);
        exit(1);
    }
    else 
    {
        // parent
        int status = 0;
        pid_t rid = waitpid(id, &status, 0);
        if (rid > 0)
        {
            printf("wait success!\n");
            //to do
        }
    }

    return 0;
}

int main()
{
    char command_line[MAXSIZE] = {0};
    while(1)
    {
        // 1.打印字符串
        PrintCommandLine();
        // 2.获取用户输入
        if (0 == GetCommandLine(command_line, sizeof(command_line)))
                continue;
        
        printf("%s\n", command_line);
        // 3.解析命令
        ParseCommand(command_line);
        
        // 4.判断是否为内建命令，是则父进程执行
        if (CheckBuiltInExecute())
            continue;

        // 5.子进程执行命令
        ExecuteCommand();
    }
    return 0;
}
